package com.ruoyi.dataserver.service.impl;

import com.ruoyi.dataserver.constant.PipelineLayoutTypeContants;
import com.ruoyi.dataserver.service.PlanningService;
import com.ruoyi.dataserver.constant.PipelineTypeContants;
import com.ruoyi.dataserver.service.ISearchTableService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName intelligent-city
 * @Package com.lab.dataserver.service.impl
 * @ClassName PlanningServiceImpl
 * @Description 模拟规划
 * @Company lab
 * @Author dongxiang
 * @Date 2020/7/29 10:14
 * @UpdateUser
 * @UpdateDate
 * @UpdateRemark
 * @Version 1.0.0
 */
@Service
public class PlanningServiceImpl implements PlanningService {

	@Autowired
	JdbcTemplate jdbcTemplate;

	@Autowired
	public ISearchTableService tableService;

	// 覆土深度标准
	// |-----------------------------------------------------------------------------------------|
	// |  最小  |     电    力    |    电    信     |    热    力     |        |        |        |
	// |  覆土  |-----------------|-----------------|-----------------|  燃气  |  供水  |  排水  |
	// |  深度  |  直埋  |  管沟  |  直埋  |  管沟  |  直埋  |  管沟  |        |        |        |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 人行道 |  0.5   |  0.4   |  0.7   |  0.4   |  0.5   |  0.2   |  0.6   |  0.6   |  0.6   |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 车行道 |  0.7   |  0.5   |  0.8   |  0.7   |  0.7   |  0.2   |  0.7   |  0.7   |  0.7   |
	// |-----------------------------------------------------------------------------------------|
	private Map<Integer,double[]> mStandardTableCover = new HashMap<Integer,double[]>() {{
		put(0,new double[]{0.5, 0.4, 0.7, 0.4, 0.5, 0.2, 0.6, 0.6, 0.6});
		put(1,new double[]{0.7, 0.5, 0.8, 0.7, 0.7, 0.2, 0.7, 0.7, 0.7});
	}};

	// 垂直距离标准
	// |--------------------------------------------------------------------------------|
	// |  最小  |        |        |        |        |    电    信     |     电    力    |
	// |  垂直  |  给水  |  排水  |  热力  |  燃气  |-----------------|-----------------|
	// |  净距  |        |        |        |        |  直埋  |  管块  |  直埋  |  管沟  |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 给水   |  0.15  |        |        |        |        |        |        |        |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 排水   |  0.4   |  0.15  |        |        |        |        |        |        |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 热力   |  0.15  |  0.15  |  0.15  |        |        |        |        |        |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 燃气   |  0.15  |  0.15  |  0.15  |  0.15  |        |        |        |        |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 电|直埋|  0.5   |  0.5   |  0.15  |  0.5   |  0.25  |  0.25  |        |        |
	// |   |----|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 信|管块|  0.15  |  0.15  |  0.15  |  0.15  |  0.25  |  0.25  |        |        |
	// |--------|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 电|直埋|  0.15  |  0.5   |  0.5   |  0.5   |  0.5   |  0.5   |  0.5   |  0.5   |
	// |   |----|--------|--------|--------|--------|--------|--------|--------|--------|
	// | 力|管沟|  0.15  |  0.5   |  0.5   |  0.15  |  0.5   |  0.5   |  0.5   |  0.5   |
	// |--------------------------------------------------------------------------------|
	private Map<Integer,double[]> mStandardTableVertical = new HashMap<Integer,double[]>() {
		{
			put(0,new double[]{0.15, 0.4, 0.15, 0.15, 0.5, 0.15, 0.15, 0.15});
			put(1,new double[]{0.4, 0.15, 0.15, 0.15, 0.5, 0.15, 0.5, 0.5});
			put(2,new double[]{0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.5, 0.5});
			put(3,new double[]{0.15, 0.15, 0.15, 0.15, 0.5, 0.15, 0.5, 0.15});
			put(4,new double[]{0.5, 0.5, 0.15, 0.5, 0.25, 0.25, 0.5, 0.5});
			put(5,new double[]{0.15, 0.15, 0.15, 0.15, 0.25, 0.25, 0.5, 0.5});
			put(6,new double[]{0.15, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5});
			put(7,new double[]{0.15, 0.5, 0.5, 0.15, 0.5, 0.5, 0.5, 0.5});
		}
	};

	// 水平距离标准
	// |--------------------------------------------------------------------------------------------------------------------------------|
	// |    最小   |    给    水     |        |             燃          气                 |    热    力     |        |     电    信    |
	// |    水平   |-----------------|  排水  |--------------------------------------------|-----------------|  电力  |-----------------|
	// |    净距   |d<=200mm|d>200mm |        |  低压  | 中压小 | 中压大 | 高压小 | 高压大 |  直埋  |  地沟  |        |  直埋  |  管道  |
	// |-----------|-----------------|--------|--------------------------|--------|--------|-----------------|--------|-----------------|
	// | 给|d<=200 |                 |  1.0   |                          |        |        |                 |        |                 |
	// |   |-------|                 |--------|           0.5            |  1.0   |  1.5   |       1.5       |  0.5   |       1.0       |
	// | 水|d>200  |                 |  1.5   |                          |        |        |                 |        |                 |
	// |-----------|-----------------|--------|--------------------------|--------|--------|-----------------|--------|-----------------|
	// | 排水      |  1.0   |  1.5   |        |   1.0  |       1.2       |  1.5   |  2.0   |       1.5       |  0.5   |       1.0       |
	// |-----------|-----------------|--------|--------------------------------------------|-----------------|--------|-----------------|
	// |   |低压   |                 |  1.0   |                                            |       1.0       |        |        |        |
	// |   |-------|                 |--------|                                            |-----------------|        |        |        |
	// | 燃|中压小 |       0.5       |        |             DN <= 300mm 0.4                |        |        |  0.5   |  0.5   |  1.0   |
	// |   |-------|                 |  1.2   |                                            |  1.0   |  1.5   |        |        |        |
	// |   |中压大 |                 |        |                                            |        |        |        |        |        |
	// |   |-------|-----------------|--------|                                            |-----------------|--------|-----------------|
	// | 气|高压小 |       1.0       |  1.5   |             DN >  300mm 0.5                |  1.5   |  2.0   |  1.0   |       1.0       |
	// |   |-------|-----------------|--------|                                            |-----------------|--------|-----------------|
	// |   |高压大 |       1.5       |  2.0   |                                            |  2.0   |  4.0   |  1.5   |       1.5       |
	// |-----------|-----------------|--------|--------------------------------------------|-----------------|--------|-----------------|
	// | 热|直埋   |                 |        |        |       1.0       |  1.5   |  2.0   |                 |        |                 |
	// |   |-------|       1.5       |  1.5   |  1.0   |-----------------|--------|--------|                 |  2.0   |       1.0       |
	// | 力|地沟   |                 |        |        |       1.5       |  2.0   |  4.0   |                 |        |                 |
	// |-----------|-----------------|--------|--------------------------|--------|--------|-----------------|--------|-----------------|
	// | 电力      |        0.5      |  0.5   |           0.5            |  1.0   |  1.5   |       2.0       |        |       0.5       |
	// |-----------|-----------------|--------|--------------------------|--------|--------|-----------------|--------|-----------------|
	// | 电|直埋   |                 |        |           0.5            |        |        |                 |        |                 |
	// |   |-------|       1.0       |  1.0   |--------------------------|  1.0   |  1.5   |       1.0       |  0.5   |       1.0       |
	// | 信|管道   |                 |        |           1.0            |        |        |                 |        |                 |
	// |--------------------------------------------------------------------------------------------------------------------------------|
	// 其中:
	// 燃气低压  ： p <= 0.05Mpa
	// 燃气中压小： 0.05Mpa < p <= 0.2 Mpa
	// 燃气中压大： 0.2 Mpa < p <= 0.4 Mpa
	// 燃气高压小： 0.4 Mpa < p <= 0.8 Mpa
	// 燃气高压大： 0.8 Mpa < p <= 1.6 Mpa
	private Map<Integer,double[]> mStandardTableHorizontal = new HashMap<Integer,double[]>() {
		{
			put(0,new double[]{0.0, 0.0, 1.0, 0.5, 0.5, 0.5, 1.0, 1.5, 1.5, 1.5, 0.5, 1.0, 1.0});
			put(1,new double[]{0.0, 0.0, 1.5, 0.5, 0.5, 0.5, 1.0, 1.5, 1.5, 1.5, 0.5, 1.0, 1.0});
			put(2,new double[]{1.0, 1.5, 0.0, 1.0, 1.2, 1.2, 1.5, 2.0, 1.5, 1.5, 0.5, 1.0, 1.0});
			put(3,new double[]{0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 0.5, 0.5, 1.0});
			put(4,new double[]{0.5, 0.5, 1.2, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.5, 0.5, 0.5, 1.0});
			put(5,new double[]{0.5, 0.5, 1.2, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.5, 0.5, 0.5, 1.0});
			put(6,new double[]{1.0, 1.0, 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.5, 2.0, 1.0, 1.0, 1.0});
			put(7,new double[]{1.5, 1.5, 2.0, 0.5, 0.5, 0.5, 0.5, 0.5, 2.0, 4.0, 1.5, 1.5, 1.5});
			put(8,new double[]{1.5, 1.5, 1.5, 1.0, 1.0, 1.0, 1.5, 2.0, 0.0, 0.0, 2.0, 1.0, 1.0});
			put(9,new double[]{1.5, 1.5, 1.5, 1.0, 1.5, 1.5, 2.0, 4.0, 0.0, 0.0, 2.0, 1.0, 1.0});
			put(10,new double[]{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.5, 2.0, 2.0, 0.0, 0.5, 0.5});
			put(11,new double[]{1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 1.0, 1.5, 1.0, 1.0, 0.5, 1.0, 1.0});
			put(12,new double[]{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.5, 1.0, 1.0, 0.5, 1.0, 1.0});
		}
	};


	/**
	 * @Title getCoverLegalDistance
	 * @Description 获取覆土标准距离
	 * @param DM
	 * @param MSLX
	 * @return double
	 * @author dongxiang
	 * @date 2020/7/30 11:45
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public double getCoverLegalDistance(String DM,Integer MSLX){
		int row = 1, col = 0;
		Integer lineType = getPipelineType(DM);
		switch (lineType) {
			case PipelineTypeContants.Electricity:  // 电力
				if (MSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) col = 0;
				else col = 1;
				break;
			case PipelineTypeContants.Telegraphy:   // 电信
				if (MSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) col = 2;
				else col = 3;
				break;
			case PipelineTypeContants.Energetics:   // 热力
				if (MSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) col = 4;
				else col = 5;
				break;
			case PipelineTypeContants.FeedWater:    // 供水
				col = 6;
				break;
			case PipelineTypeContants.Sewage:       // 排水
			case PipelineTypeContants.Rain:
				col = 7;
				break;
			case PipelineTypeContants.Gas:          // 燃气
				col = 8;
				break;
			case PipelineTypeContants.Streetlamp:          // 路灯
				col = 0;
				break;
			default:
				return 0.0;
		}
		return mStandardTableCover.get(row)[col];
	}

	/**
	 * @Title getHorizontalLegalDistance
	 * @Description 获取两管段水平最短合法距离
	 * @param targetDM
	 * @param targetMSLX
	 * @param referDM
	 * @param referMSLX
	 * @return double
	 * @author dongxiang
	 * @date 2020/7/30 9:41
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public double getHorizontalLegalDistance(String targetDM,Integer targetMSLX,
											 String referDM,Integer referMSLX){
		Integer targetLineType = getPipelineType(targetDM);
		Integer referLineType = getPipelineType(referDM);
		int row = 0, col = 0;

		switch (targetLineType) {
			case PipelineTypeContants.FeedWater:    // 供水, 0-1
				row = 0;
				break;
			case PipelineTypeContants.Sewage:       // 排水, 2
			case PipelineTypeContants.Rain:
				row = 2;
				break;
			case PipelineTypeContants.Gas:          // 燃气, 3-7
				row = 3;
				break;
			case PipelineTypeContants.Energetics:   // 热力, 8-9
				if (targetMSLX.equals(PipelineLayoutTypeContants.Layout_ZHIMAI)) row = 8;
				else row = 9;
				break;
			case PipelineTypeContants.Electricity:  // 电力, 10
				row = 10;
				break;
			case PipelineTypeContants.Telegraphy:   // 电信, 11-12
				if (targetMSLX.equals(PipelineLayoutTypeContants.Layout_ZHIMAI)) row = 11;
				else row = 12;
				break;
			case PipelineTypeContants.Streetlamp:          // 路灯
				row = 10;
				break;
			default:
				return 0.0;
		}
		switch (referLineType) {
			case PipelineTypeContants.FeedWater:    // 供水, 0-1
				col = 0;
				break;
			case PipelineTypeContants.Sewage:       // 排水, 2
			case PipelineTypeContants.Rain:
				col = 2;
				break;
			case PipelineTypeContants.Gas:          // 燃气, 3-7
				col = 3;
				break;
			case PipelineTypeContants.Energetics:   // 热力, 8-9
				if (referMSLX.equals(PipelineLayoutTypeContants.Layout_ZHIMAI)) col = 8;
				else col = 9;
				break;
			case PipelineTypeContants.Electricity:  // 电力, 10
				col = 10;
				break;
			case PipelineTypeContants.Telegraphy:   // 电信, 11-12
				if (referMSLX.equals(PipelineLayoutTypeContants.Layout_ZHIMAI)) col = 11;
				else col = 12;
				break;
			case PipelineTypeContants.Streetlamp:          // 路灯
				col = 10;
				break;
			default:
				return 0.0;
		}
		return mStandardTableHorizontal.get(row)[col];
	}

	/**
	 * @Title getHorizontalLegalDistance
	 * @Description 获取两管段垂直最短合法距离
	 * @param targetDM
	 * @param targetMSLX
	 * @param referDM
	 * @param referMSLX
	 * @return double
	 * @author dongxiang
	 * @date 2020/7/30 10:58
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public double getVerticalLegalDistance(String targetDM,Integer targetMSLX,
										   String referDM,Integer referMSLX){
		int row = 0, col = 0;
		Integer targetLineType = getPipelineType(targetDM);
		Integer referLineType = getPipelineType(referDM);
		switch (targetLineType) {
			case PipelineTypeContants.FeedWater:    // 供水
				row = 0;
				break;
			case PipelineTypeContants.Sewage:       // 排水
			case PipelineTypeContants.Rain:
				row = 1;
				break;
			case PipelineTypeContants.Energetics:   // 热力
				row = 2;
				break;
			case PipelineTypeContants.Gas:          // 燃气
				row = 3;
				break;
			case PipelineTypeContants.Telegraphy:   // 电信
				if (targetMSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) row = 4;
				else row = 5;
				break;
			case PipelineTypeContants.Electricity:  // 电力
				if (targetMSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) row = 6;
				else row = 7;
				break;
			case PipelineTypeContants.Streetlamp:          // 路灯
				row = 6;
				break;
			default:
				return 0.0;
		}
		switch (referLineType) {
			case PipelineTypeContants.FeedWater:    // 供水
				col = 0;
				break;
			case PipelineTypeContants.Sewage:       // 排水
			case PipelineTypeContants.Rain:
				col = 1;
				break;
			case PipelineTypeContants.Energetics:   // 热力
				col = 2;
				break;
			case PipelineTypeContants.Gas:          // 燃气
				col = 3;
				break;
			case PipelineTypeContants.Telegraphy:   // 电信
				if (referMSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) col = 4;
				else col = 5;
				break;
			case PipelineTypeContants.Electricity:  // 电力
				if (referMSLX == PipelineLayoutTypeContants.Layout_ZHIMAI) col = 6;
				else col = 7;
				break;
			case PipelineTypeContants.Streetlamp:          // 路灯
				col = 6;
				break;
			default:
				return 0.0;
		}
		return mStandardTableHorizontal.get(row)[col];
	}

	/**
	 * @Title getVerticalDistance
	 * @Description 获取管段实际垂直最短距离
	 * @param targetQDMS
	 * @param targetZDMS
	 * @param referSQDMS
	 * @param referZDMS
	 * @return double
	 * @author dongxiang
	 * @date 2020/7/30 10:49
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public double getVerticalDistance(double targetQDMS,double targetZDMS,
									  double referSQDMS,double referZDMS){

		// 交叉
		if (targetQDMS - referSQDMS >= 0 && targetZDMS - referZDMS <= 0){
			return 0;
		}
		if (referSQDMS - targetQDMS >= 0 && referZDMS - targetZDMS <= 0){
			return 0;
		}
		// 不交叉
		double minTargetQDMS = Math.min(Math.abs(targetQDMS - referSQDMS),Math.abs(targetQDMS - referZDMS));
		double minTargetZDMS = Math.min(Math.abs(targetZDMS - referSQDMS),Math.abs(targetZDMS - referZDMS));
		return Math.min(minTargetQDMS,minTargetZDMS);
	}


	public static double[] GaussToBLToGauss(double longitude, double latitude){
		double[] output = new double[2];
		double longitude1,latitude1, longitude0, X0,Y0, xval,yval;
		//NN曲率半径，测量学里面用N表示
		//M为子午线弧长，测量学里用大X表示
		//fai为底点纬度，由子午弧长反算公式得到，测量学里用Bf表示
		//R为底点所对的曲率半径，测量学里用Nf表示
		double a,f, e2,ee, NN, T,C,A, M, iPI;
		iPI = 0.0174532925199433; //3.1415926535898/180.0;
		a=6378137.0; f=1/298.257222101; //CGCS2000坐标系参数
		//a=6378137.0; f=1/298.2572236; //wgs84坐标系参数
		longitude0 = 117.0;//中央子午线 根据实际进行配置
		longitude0 = longitude0 * iPI ;//中央子午线转换为弧度
		longitude1 = longitude * iPI ; //经度转换为弧度
		latitude1 = latitude * iPI ; //纬度转换为弧度
		e2=2*f-f*f;
		ee=e2*(1.0-e2);
		NN=a/Math.sqrt(1.0-e2*Math.sin(latitude1)*Math.sin(latitude1));
		T=Math.tan(latitude1)*Math.tan(latitude1);
		C=ee*Math.cos(latitude1)*Math.cos(latitude1);
		A=(longitude1-longitude0)*Math.cos(latitude1);
		M=a*((1-e2/4-3*e2*e2/64-5*e2*e2*e2/256)*latitude1-(3*e2/8+3*e2*e2/32+45*e2*e2
				*e2/1024)*Math.sin(2*latitude1)
				+(15*e2*e2/256+45*e2*e2*e2/1024)*Math.sin(4*latitude1)-(35*e2*e2*e2/3072)*Math.sin(6*latitude1));
		xval = NN*(A+(1-T+C)*A*A*A/6+(5-18*T+T*T+72*C-58*ee)*A*A*A*A*A/120);
		yval = M+NN*Math.tan(latitude1)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
				+(61-58*T+T*T+600*C-330*ee)*A*A*A*A*A*A/720);
		X0 = 500000L;
		Y0 = 0;
		xval = xval+X0; yval = yval+Y0;

		//转换为投影
		output[0] = xval;
		output[1] = yval;
		return output;
	}


	/**
	 * @Title getHorizontalDistance
	 * @Description 获取两管段实际水平最短距离
	 * @param targetSNODID
	 * @param targetENODID
	 * @param targetGJ
	 * @param referSNODID
	 * @param referENODID
	 * @param referGJ
	 * @return double
	 * @author dongxiang
	 * @date 2020/7/30 9:42
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public double getHorizontalDistance(String targetSNODID,String targetENODID,String targetGJ,
									  	String referSNODID,String referENODID,String referGJ
										){
		String[] line1Start = targetSNODID.split("-");
		String[] line1End = targetENODID.split("-");
		String[] line2Start = referSNODID.split("-");
		String[] line2End = referENODID.split("-");
		double[] line1StartD = GaussToBLToGauss(new Double(line1Start[0]),new Double(line1Start[1]));
		double[] line1EndD = GaussToBLToGauss(new Double(line1End[0]),new Double(line1End[1]));
		double[] line2StartD = GaussToBLToGauss(new Double(line2Start[1]),new Double(line2Start[0]));
		double[] line2EndD = GaussToBLToGauss(new Double(line2End[1]),new Double(line2End[0]));
		// 中心线最短距离
		double centerDistance = squreDistanceSegmentToSegment(line1StartD[0],line1StartD[1],0,
				line1EndD[0],line1EndD[1],0,
				line2StartD[0],line2StartD[1],0,
				line2EndD[0],line2EndD[1],0);
		/*double centerDistance = squreDistanceSegmentToSegment(new Double(line1Start[0]),new Double(line1Start[1]),0,
				new Double(line1End[0]),new Double(line1End[1]),0,
				new Double(line2Start[1]),new Double(line2Start[0]),0,
				new Double(line2End[1]),new Double(line2End[0]),0);*/

		// 扣除管径,真实距离
		double targetGJDouble = 0, referGJDouble = 0;

		if (StringUtils.indexOf(targetGJ,"X") > -1){
			String[] targetGJArray = targetGJ.split("X");
			targetGJDouble = Math.max(Integer.parseInt(targetGJArray[0]),Integer.parseInt(targetGJArray[1]));
		}else if(StringUtils.indexOf(targetGJ,"x") > -1){
			String[] targetGJArray = targetGJ.split("x");
			targetGJDouble = Math.max(Integer.parseInt(targetGJArray[0]),Integer.parseInt(targetGJArray[1]));
		}else{
			targetGJDouble = new Double("".equals(StringUtils.trim(targetGJ)) ? "0" : targetGJ);
		}

		if (!"".equals(StringUtils.trim(referGJ)) && StringUtils.indexOf(StringUtils.trim(referGJ),"X") > -1){
			String[] referGJArray = referGJ.split("X");
			referGJDouble = Math.max(Integer.parseInt(referGJArray[0]),Integer.parseInt(referGJArray[1]));
		}else if(!"".equals(StringUtils.trim(referGJ)) && StringUtils.indexOf(StringUtils.trim(referGJ),"x") > -1){
			String[] referGJArray = referGJ.split("x");
			referGJDouble = Math.max(Integer.parseInt(referGJArray[0]),Integer.parseInt(referGJArray[1]));

		}else{
			referGJDouble = new Double("".equals(StringUtils.trim(referGJ)) ? "0.0" : StringUtils.trim(referGJ));
		}
		double distance = centerDistance - targetGJDouble/(2*1000) - referGJDouble/(2*1000);
		// double distance = centerDistance;
		if (distance < 0){
			distance = 0;
		}
		return distance;
	}

	/**
	 * @Title getPipelineType
	 * @Description 获取管段类型，以计算最短距离标准
	 * @param dm
	 * @return java.lang.Integer
	 * @author dongxiang
	 * @date 2020/7/30 9:43
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public Integer getPipelineType(String dm){
		Integer pipeLineType = 0;
		switch (dm) {
			case "GDX":  //供电管线
				pipeLineType= PipelineTypeContants.Electricity;// 电力
				break;
			case "LDX":   //路灯管线
				pipeLineType= PipelineTypeContants.Electricity;  // 电力
				break;
			case "JTX":   //交通信号管线
				pipeLineType= PipelineTypeContants.Electricity;// 电力
				break;
			case "GGX":  //广告管线
				pipeLineType= PipelineTypeContants.Electricity;  //电力
				break;
			case "DHX":  //电话管线
				pipeLineType= PipelineTypeContants.Telegraphy;// 通信
				break;
			case "XXX":   //信息网络管线
				pipeLineType= PipelineTypeContants.Telegraphy;// 通信
				break;
			case "DTX":   //电力通讯管线
				pipeLineType= PipelineTypeContants.Telegraphy;// 通信
				break;
			case "ZYX":   //专用通讯管线
				pipeLineType= PipelineTypeContants.Telegraphy;// 通信
				break;
			case "YXX":   //有线电视管线
				pipeLineType= PipelineTypeContants.Telegraphy;// 通信
				break;
			case "GBX":   //广播管线
				pipeLineType= PipelineTypeContants.Telegraphy;// 通信
				break;

			case "SYG":   //原水管线
				pipeLineType= PipelineTypeContants.FeedWater;// 供水
				break;
			case "SSG":    //输水管线
				pipeLineType= PipelineTypeContants.FeedWater;// 供水
				break;
			case "XFS":   //消防水管线
				pipeLineType= PipelineTypeContants.FeedWater;// 供水
				break;
			case "YSG":   //雨水管线
				pipeLineType= PipelineTypeContants.Rain;   //排水
				break;
			case "WSG":   //污水管线
				pipeLineType= PipelineTypeContants.Sewage;//排水
				break;
			case "HSG":   //合流管线
				pipeLineType= PipelineTypeContants.Rain;//排水
				break;
			case "TRQ":
				pipeLineType= PipelineTypeContants.Gas;   // 燃气
				break;
			case "RSG":
				pipeLineType= PipelineTypeContants.Energetics;  // 热力
				break;
			case "ZQG":   //蒸汽管线
				pipeLineType= PipelineTypeContants.Energetics;  // 热力
				break;
			case "YLG":   //油料管线
				pipeLineType= PipelineTypeContants.Industry;  // 工业
				break;
			case "ZYG":   //重油管线
				pipeLineType= PipelineTypeContants.Industry;  // 工业
				break;
			case "BMG":
				pipeLineType= PipelineTypeContants.Unknown;  // 不明
				break;
			case "PZG":   //排渣管线
				pipeLineType= PipelineTypeContants.Industry;  // 工业
				break;
			default:
				pipeLineType= PipelineTypeContants.Unknown;  // 不明
				break;
		}
		return pipeLineType;
	}

	/**
	 * @Title getLines
	 * @Description 获取管道信息（類型）
	 * @param dm
	 * @return java.util.List
	 * @author dongxiang
	 * @date 2020/8/4 11:51
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public List getLines(String dm){
		String tableName = tableService.searchLineTable(dm);
		String sql = "select US_ID,DM,ENODID,SNODID from " + tableName;
		try{
			List lines = jdbcTemplate.queryForList(sql);
			return lines;
		}catch (DataAccessException e){
			return null;
		}
	}

	public List<Map> getLines(String dm,Integer startId,Integer limit,Integer size){
		String tableName = tableService.searchLineTable(dm);
		String sql = "select OBJECTID,US_ID,DM,ENODID,SNODID from (select OBJECTID,US_ID,DM,ENODID,SNODID,rownum as num from " + tableName + ") a where (num between " + limit +" and "+ (limit + size) + ") and OBJECTID > " + startId + " order by  OBJECTID asc";
		try{
			List lines = jdbcTemplate.queryForList(sql);
			return lines;
		}catch (DataAccessException e){
			return null;
		}
	}

	public Integer getLineCount(String dm){
		String tableName = tableService.searchLineTable(dm);
		String sql = "select count(*) from "+ tableName;
		try{
			Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
			return count;
		}catch (DataAccessException e){
			return null;
		}
	}

	/**
	 * @Title getLineInfo
	 * @Description 获取管道信息（通用）
	 * @param usid
	 * @param dm
	 * @return java.util.Map
	 * @author dongxiang
	 * @date 2020/7/30 9:43
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public Map getLineInfo(String usid,String dm){
		String tableName = tableService.searchLineTable(dm);
		String sql = "select * from \"" + tableName + "\" where US_ID ='" + usid +"'";
		try{
			Map<String,Object> lineInfo = jdbcTemplate.queryForMap(sql);
			return lineInfo;
		}catch (DataAccessException e){
			return null;
		}

	}

	public boolean IsEqual(double d1, double d2)
	{
		if (Math.abs(d1 - d2) < 1e-7)
			return true;
		return false;
	}
	private static double EARTH_RADIUS = 6378.137;// 单位千米
	private static double getRadian(double degree) {

		return degree * Math.PI / 180.0;

	}
	public static double getDistance(double lat1, double lng1, double lat2, double lng2) {

		double radLat1 = getRadian(lat1);

		double radLat2 = getRadian(lat2);

		double a = radLat1 - radLat2;// 两点纬度差

		double b = getRadian(lng1) - getRadian(lng2);// 两点的经度差

		double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1)

				* Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));

		s = s * EARTH_RADIUS;

		return s * 1000;

	}

	/**
	 * @Title squreDistanceSegmentToSegment
	 * @Description 计算两线段三维距离
	 * @param x1
	 * @param y1
	 * @param z1
	 * @param x2
	 * @param y2
	 * @param z2
	 * @param x3
	 * @param y3
	 * @param z3
	 * @param x4
	 * @param y4
	 * @param z4
	 * @return double
	 * @author dongxiang
	 * @date 2020/7/30 9:44
	 * @UpdateUser
	 * @UpdateDate
	 * @UpdateRemark
	 */
	public double squreDistanceSegmentToSegment(double x1, double y1, double z1,
												double x2, double y2, double z2,
												double x3, double y3, double z3,
												double x4, double y4, double z4)
	{
		// 解析几何通用解法，可以求出点的位置，判断点是否在线段上
		// 算法描述：设两条无限长度直线s、t,起点为s0、t0，方向向量为u、v
		// 最短直线两点：在s1上为s0+sc*u，在t上的为t0+tc*v
		// 记向量w为(s0+sc*u)-(t0+tc*v),记向量w0=s0-t0
		// 记a=u*u，b=u*v，c=v*v，d=u*w0，e=v*w0——(a)；
		// 由于u*w=、v*w=0，将w=-tc*v+w0+sc*u带入前两式得：
		// (u*u)*sc - (u*v)*tc = -u*w0  (公式2)
		// (v*u)*sc - (v*v)*tc = -v*w0  (公式3)
		// 再将前式(a)带入可得sc=(be-cd)/(ac-b2)、tc=(ae-bd)/(ac-b2)——（b）
		// 注意到ac-b2=|u|2|v|2-(|u||v|cosq)2=(|u||v|sinq)2不小于0
		// 所以可以根据公式（b）判断sc、tc符号和sc、tc与1的关系即可分辨最近点是否在线段内
		// 当ac-b2=0时，(公式2)(公式3)独立，表示两条直线平行。可令sc=0单独解出tc
		// 最终距离d（L1、L2）=|（P0-Q0)+[(be-cd)*u-(ae-bd)v]/(ac-b2)|
		double ux = x2 - x1;
		double uy = y2 - y1;
		double uz = z2 - z1;

		double vx = x4 - x3;
		double vy = y4 - y3;
		double vz = z4 - z3;

		double wx = x1 - x3;
		double wy = y1 - y3;
		double wz = z1 - z3;

		double a = (ux * ux + uy * uy + uz * uz); //u*u
		double b = (ux * vx + uy * vy + uz * vz); //u*v
		double c = (vx * vx + vy * vy + vz * vz); //v*v
		double d = (ux * wx + uy * wy + uz * wz); //u*w
		double e = (vx * wx + vy * wy + vz * wz); //v*w
		double dt = a * c - b * b;

		double sd = dt;
		double td = dt;

		double sn = 0.0;//sn = be-cd
		double tn = 0.0;//tn = ae-bd

		if (IsEqual(dt, 0.0))
		{
			//两直线平行
			sn = 0.0;    //在s上指定取s0
			sd = 1.00;   //防止计算时除0错误

			tn = e;      //按(公式3)求tc
			td = c;
		}
		else
		{
			sn = (b * e - c * d);
			tn = (a * e - b * d);
			if (sn < 0.0)
			{
				//最近点在s起点以外，同平行条件
				sn = 0.0;
				tn = e;
				td = c;
			}
			else if (sn > sd)
			{
				//最近点在s终点以外(即sc>1,则取sc=1)
				sn = sd;
				tn = e + b; //按(公式3)计算
				td = c;
			}
		}
		if (tn < 0.0)
		{
			//最近点在t起点以外
			tn = 0.0;
			if (-d < 0.0) //按(公式2)计算，如果等号右边小于0，则sc也小于零，取sc=0
				sn = 0.0;
			else if (-d > a) //按(公式2)计算，如果sc大于1，取sc=1
				sn = sd;
			else
			{
				sn = -d;
				sd = a;
			}
		}
		else if (tn > td)
		{
			tn = td;
			if ((-d + b) < 0.0)
				sn = 0.0;
			else if ((-d + b) > a)
				sn = sd;
			else
			{
				sn = (-d + b);
				sd = a;
			}
		}

		double sc = 0.0;
		double tc = 0.0;

		if (IsEqual(sn, 0.0))
			sc = 0.0;
		else
			sc = sn / sd;

		if (IsEqual(tn, 0.0))
			tc = 0.0;
		else
			tc = tn / td;

		double dx = wx + (sc * ux) - (tc * vx);
		double dy = wy + (sc * uy) - (tc * vy);
		double dz = wz + (sc * uz) - (tc * vz);
		double res =  dx * dx + dy * dy + dz * dz;
		if (res > 0){
			return Math.sqrt(res);
		}else{
			return 0;
		}
	}

}
